/* 有女羅馬字
 *
 * https://github.com/BYVoid/ytenx/blob/master/ytenx/sync/kyonh/PrengQim.txt
 *
 * 本版說明：
 *
 * - 基於韻典網數據，並參照有女同車原版《〈廣韻〉全字表》（下稱「原表」）有所校正
 * - 目前推導器預設資料與原表有數十小韻在聲母、開合、等、重紐類等歸類有所不同，但除個別外均不影響原拼寫系統（需擴展原表拼寫系統的，列為選項）
 * - 旨韻（脂上聲）若干精、章組小韻，韻母寫為B類，與他處精章組均用A類不合，現修正
 * - 崇開三眞上（濜）：真諄上去聲莊組開口，原表及拼寫均析為臻韻上去聲，惟此小韻遺漏，現修正
 * - 莊合三真入（𠭴）：韻母寫為A類，與他處莊組均用B類不合，現修正（雖然不排除是因該小韻列於術韻而非質韻，但術韻下亦有「率」小韻用B類拼作 shwyt，故當以B類為正）
 * - 以開一寒入（poem表「䔾」）：原表無寒韻拼章組日以母例，但有談韻書母例與之平行，故可拼作 jat
 * - 幫清B入（碧）：原表處理為清韻合口作 pvek，與「辟」小韻開合對立。亦可處理為庚三即 pyak。原表清韻無B類，但可據體系推出處理為「清B」時的拼法 pyek。本代碼同時支持三種處理法
 *
 * @author SyiMyuZya
 */

// 可調整參數
if (!音韻地位) {
  return [
    // 祭廢韻平上（章組云以日母）
    // - 停用（預設）：不認可祭廢非去聲，歸為齊灰咍韻
    // - 啟用：認可該類地位（實際上祭、齊韻推導結果相同，僅廢與灰咍會不同）
    ['蟹攝三等平上', false],

    // 莊組眞韻開口上、去聲
    // - 停用（預設）：按原表，均處理為臻韻
    // - 啟用：認可莊組眞韻
    ['莊組眞韻開口', false],

    // 清B處理法（推導器預設資料無此類，僅適用於其他資料音韻地位）
    // - `'清B'`（預設）：按清B拼寫
    // - `'合口'`：按原表處理，以清韻合口拼寫
    // - `'庚三'`：不認可清韻B類，視同庚三
    ['清B脣音', [1, '清B', '合口', '庚三']],
  ];
}

const is = (...x) => 音韻地位.屬於(...x);

// 調整音韻地位

音韻地位.呼 && is`脣音` && (音韻地位 = 音韻地位.調整({ 呼: null }));
音韻地位.重紐 && is`陽蒸幽韻` && (音韻地位 = 音韻地位.調整({ 重紐: null }));
is`莊組 欣韻` && (音韻地位 = 音韻地位.調整({ 韻: '臻' }));

// 選項相關
if (!選項.蟹攝三等平上 && is`祭廢韻 平上聲`) {
  音韻地位 = 音韻地位.調整(
    is`祭韻`
      ? { 韻: '齊', 等: '四' }
      : { 韻: is`開口` ? '咍' : '灰', 等: '一' },
  );
} else if (!選項.莊組眞韻開口 && is`莊組 眞韻 開口`) {
  音韻地位 = 音韻地位.調整({ 韻: '臻' });
} else if (選項.清B脣音 === '庚三' && is`幫組 清韻 重紐B類`) {
  音韻地位 = 音韻地位.調整({ 韻: '庚', 重紐: null });
}

/**
 * 依次匹配列表 `rules` 中的規則，返回第一項測試為 true 的對應結果。
 * 無匹配規則時抛出異常，`name` 會包含於異常信息中。
 *
 * `rules` 每項為 `[條件, 結果]`
 * 條件可為：
 * - 字串，會用 `音韻地位.屬於` 測試
 * - 函數，會直接調用並測試返回結果
 * - 其他，直接測試真值
 */
function 規則(name, rules) {
  for (const [rule, res] of rules) {
    if (typeof rule === 'string') {
      if (is(rule.replace(/　/g, ''))) {
        return res;
      }
    } else if (typeof rule === 'function') {
      if (rule()) {
        return res;
      }
    } else if (rule) {
      return res;
    }
  }
  throw new Error(`無${name}規則：${音韻地位.描述}`);
}

// 聲母

// prettier-ignore
let 母 = {
  幫: 'p',  滂: 'ph', 並: 'b',  明: 'm',
  端: 't',  透: 'th', 定: 'd',  泥: 'n',
  知: 't',  徹: 'th', 澄: 'd',  孃: 'n',
  精: 'z',  清: 'c',  從: 'dz',           心: 's',  邪: 'sz',
  莊: 'tr', 初: 'ch', 崇: 'dr',           生: 'sh', 俟: 'zh',
  章: 'tj', 昌: 'tc', 船: 'dj', 日: 'r',  書: 'sj', 常: 'zj',
  見: 'k',  溪: 'q',  羣: 'g',  疑: 'ng',
  影: '',   曉: 'x',  匣: 'h',  云: 'h',
                                以: 'j',
                                來: 'l',
}[音韻地位.母];

if (母 === undefined) {
  throw new Error(`無聲母規則: ${音韻地位.描述}`);
}

// 韻尾

let 尾 = 音韻地位.判斷(
  [
    ['遇果假攝 或 支脂之佳韻', ''],
    ['通江宕梗曾攝', 'ng'],
    ['蟹攝 或 微韻', 'i'], // 已排除佳韻
    ['臻山攝', 'n'],
    ['效流攝', 'u'],
    ['深咸攝', 'm'],
  ],
  `無韻尾規則: ${音韻地位.描述}`,
);

// 主元音

let 元 = 音韻地位.判斷(
  [
    ['歌麻　唐庚陽　泰夬廢　寒刪元　豪肴　談銜嚴凡韻', 'a'],
    ['佳支　青耕清　齊皆祭　先山仙　蕭宵　添咸鹽　韻', 'e'],
    ['　脂　　　　　　　　　眞　　　　幽　　　侵　韻', 'i'],
    ['　　　　　　　　　　　臻　　　　　　　　　　韻', 'yi'],
    ['　　　登江蒸　咍灰微　痕魂欣　侯尤　覃　　　韻', 'o'],
    ['　之　　　　　　　　　　　　　　　　　　　　韻', 'io'], // 之韻 io 的 i 視為主元音
    ['模虞　東　　　　　　　　　文　　　　　　　　韻', 'u'],
    ['　魚　冬　鍾　　　　　　　　　　　　　　　　韻', 'v'],
  ].map(([cond, ...rest]) => [cond.replace(/　/g, ''), ...rest]),
  `無主元音規則: ${音韻地位.描述}`,
);

// 介音

// 拼寫上使用合口介音的場合
const 合口 = !is`脣音`
  ? is`合口 非 文韻`
  : is`歌陽廢寒元凡灰微魂韻` || is`清韻 重紐B類 ${選項.清B脣音 === '合口'}`;

let 介 = {
  一: ['', 'u'],
  二: ['e', 'o'],
  三: ['i', 'v'],
  四: ['', 'u'],
}[音韻地位.等][+合口];

if (介 === 'i' && (元.startsWith('i') || 元.startsWith('y'))) {
  介 = '';
} else if (介 === 'e' && 元 === 'e') {
  // 二等開口 e 元音寫作 ae
  介 = '';
  元 = 'ae';
} else if (介 === 'o' && 元 === 'e') {
  // oe 上聲要雙寫 o，亦視作整體
  介 = '';
  元 = 'oe';
}

// 三等重紐、重韻
if (
  (is('重紐B類') && (選項.清B脣音 !== '合口' || !is('幫組 清韻'))) ||
  (['i', 'e'].includes(元) &&
    is`(三等 知莊組 或 云母) 非 (知組 (清韻 或 眞韻 合口))`) || // 清、諄韻知組視作A類
  is('麻庚韻 三等 或 幽韻') // 重韻
) {
  介 = {
    i: 'y',
    v: 'w',
    '': '', // 主元音為 i 時
  }[介];
  if (介 === undefined) {
    throw new Error(`無重紐重韻規則: ${音韻地位.描述}`);
  }
  if (元 === 'i') {
    元 = 'y';
  }
}

// 拼寫規則

if (is('章組 或 日以母')) {
  // 章組、日以母省略 i 介音，麻三亦省略 y 介音
  if (介.startsWith('i')) {
    介 = 介.slice(1);
  } else if (is('麻韻 三等') && !合口) {
    介 = '';
  }
} else if (is('莊組')) {
  // 莊組拼 ea 省 e，拼 io, iu, iv 省 i（不含之韻），拼 ye 省 y（支韻除外）
  if (
    (介 === 'e' && 元 === 'a') ||
    (介 === 'i' && ['o', 'u', 'v'].includes(元)) ||
    (介 === 'y' && 元 === 'e' && 尾 !== '')
  ) {
    介 = '';
  }
}

// 聲調
if (音韻地位.聲 === '入') {
  尾 = {
    m: 'p',
    n: 't',
    ng: 'k',
  }[尾];
} else if (音韻地位.聲 !== '平') {
  if (['i', 'u', 'ng'].includes(尾)) {
    尾 = {
      i: ['j', 'y'],
      u: ['v', 'w'],
      ng: ['nk', 'nq'],
    }[尾][Number(音韻地位.聲 === '去')];
  } else if (音韻地位.聲 === '上') {
    元 = ['io', 'ae', 'oe'].includes(元) ? 元[0] + 元 : 元 + 元.slice(-1);
  } else if (音韻地位.聲 === '去' && ['m', 'n'].includes(尾)) {
    尾 = 尾 + 尾;
  } else if (音韻地位.聲 === '去' && 尾 === '') {
    元 = 元 + 'h';
  } else {
    throw new Error(`無聲調規則: ${音韻地位.描述}`);
  }
}
if (尾 === undefined || 元 === undefined) {
  throw new Error(`無聲調規則: ${音韻地位.描述}`);
}

return `${母}${介}${元}${尾}`;
